using Z = Mint<998244353>;
struct node {
  int v, x, y;
};

Sieve p(200000);
void solve()
{
  int n;
  cin >> n;

  vector<vector<node>> g(n + 1);
  rep(i, 2, n) {
    int u, v, x, y;
    cin >> u >> v >> x >> y;
    int d = __gcd(x, y);
    x /= d, y /= d;
    g[u].pb({v, x, y});
    g[v].pb({u, y, x});
  }

  vvi facs(n + 1);
  vi mxp(n + 1), cnt(n + 1);
  rep(i, 1, n) {
    facs[i] = p.getPrimeFactors(i);
  }

  auto dfs = [&](auto &&dfs, int u, int fa) -> void {
    for (auto &[v, x, y] : g[u]) {
      if (v != fa) {
        for (auto &j : facs[y]) {
          cnt[j]--;
        }
        for (auto &j : facs[x]) {
          cnt[j]++;
          mxp[j] = max(mxp[j], cnt[j]); 
        }
        dfs(dfs, v, u);
        for (auto &j : facs[y]) {
          cnt[j]++;
        }
        for (auto &j : facs[x]) {
          cnt[j]--;
        }
      }
    }
  };
  dfs(dfs, 1, 0);

  auto get_ans = [&](auto &&self, int u, int fa, Z val) -> Z {
    Z ret = val;
    for (auto &[v, x, y]: g[u]) {
      if (v != fa) {
        ret += self(self, v, u, val * y * Z(x).inv());
      }
    }
    return ret;
  };

  Z val = 1;
  rep(i, 1, n) {
    val *= power<Z>(i, mxp[i]);
  }
  cout << get_ans(get_ans, 1, 0, val) << '\n';
}